<?php
namespace app\common\model;

use app\common\model\Base;

class Member extends Base
{

    static $status_remark = [
            0 => '临时会员',
            1 => '可用',
            2 => '待审核',
            3 => '禁用',
            4 => '冻结'
        ];
    static $is_agent_remark = [
            1 => '是',
            2 => '否'
        ];
    static $area_remark = [
            1 => 'A区',
            2 => 'B区'
        ];
    static $type_remark = [
            1 => '空单',
            2 => '实单'
        ];
    static $is_phone_checked_remark = [
            0 => '未验证',
            1 => '已验证'
        ];

    protected $readonly = ['id','mid','inviter_id','seter_id','agent_id'];
    protected $auto=['mid','inviter_id','seter_id','agent_id'];
    protected $insert=['create_time'];

    protected function setCreateTimeAttr(){
        return time();
    }
    protected function setMidAttr($value){
        return strtoupper($value);
    }
    protected function setInviterIdAttr($value){
        return strtoupper($value);
    }
    protected function setSeterIdAttr($value){
        return strtoupper($value);
    }
    protected function setAgentIdAttr($value){
        return strtoupper($value);
    }

    public static function status($key=null){
        if(is_null($key)){
            return self::$status_remark;
        }else{
            return self::$status_remark[$key];
        }
    }
    public static function is_agent($key=null){
        if(is_null($key)){
            return self::$is_agent_remark;
        }else{
            return self::$is_agent_remark[$key];
        }
    }
    public static function area($key=null){
        if(is_null($key)){
            return self::$area_remark;
        }else{
            return self::$area_remark[$key];
        }
    }
    public static function type($key=null){
        if(is_null($key)){
            return self::$type_remark;
        }else{
            return self::$type_remark[$key];
        }
    }
    public static function is_phone_checked($key=null){
        if(is_null($key)){
            return self::$is_phone_checked_remark;
        }else{
            return self::$is_phone_checked_remark[$key];
        }
    }

    /**
     * 获取分页列表
     * @param  [type] $where    [description]
     * @param  string $queryStr [description]
     * @param  string $baseUrl  [description]
     * @return [type]           [description]
     */
    public function getPageDatas($where,$page,$perpagenum){

        $start = ($page-1)*$perpagenum;
        
        $whereData=[];
        if(!empty($where)){
            foreach($where as $k => $wh):
                $whereData['a.'.$k] = $wh;
            endforeach;
        }
        
        $rows = $this
                ->alias('a')
                ->join('member b','a.seter_id=b.id','LEFT')
                ->join('member c','a.inviter_id=c.id','LEFT')
                ->join('member d','a.agent_id=d.id','LEFT')
                ->where($whereData)
                ->field('a.*,b.mid seter_mid,c.mid inviter_mid,d.mid agent_mid')
                ->limit($start,$perpagenum)
                ->order('a.id','DESC')->select();

        $count = $this->alias('a')->where($whereData)->count();
        $data = [];
        if($count){
            foreach($rows as $row):
                $row = $row->toArray();
                $data[] = $this->setField($row);
            endforeach;
        }

        $total_page = ceil($count/$perpagenum);
        return [
            'total_page' => $total_page,
            'curent_page' => $page,
            'count' => $count,
            'data' => $data
        ];
    }

    /**
     * 根据id查询单条数据
     * @param  [type] $mid    [description]
     * @param  [type] $fields [description]
     * @return [type]         [description]
     */
    public function getOneDataById($id,$fields=[]){
        $row = $this->field($fields)->find($id);
        if(!$row){
            $this->error='会员不存在';
            return false;
        }
        $row = $row->toArray();
        $row = $this->setField($row);
        // 会员账户
        $row['account'] = model('member_coin')->getAccountByUid($id);
        // 大区结余
        $row['jieyu'] = model('member_area_score')->getAreaScoreByUid($id);
        // 安置路径
        $row['seters'] = model('member_seter')->getSetersByUid($id);
        return $row;
    }

    /**
     * 通过uid查询会员网络
     * @param  [type] $mid [description]
     * @return [type]      [description]
     */
    public function queryMap($uid){
        $fields = ['id','mid','type','status','mname','phone','level_id','area','score_total','seter_id'];
        $topMember = $this->getOneDataById($uid,$fields);
        $memberTree = $topMember;

        // 上翻
        $memberTree['up'] = $memberTree['seter_id'];
        $memberTree['down'] = '';

        $memberTree['son'] = [];
        // 查询下级一层会员
        $son = $this->memberSon($uid,$fields);
        if($son):
            foreach($son as $k => $s):
                // 上翻,上层安置人的安置人
                $s_seters = $s['seters'];
                if(sizeof($s_seters)>=2){
                    // 上级超过两层可以上翻
                    $s['up'] = $memberTree['seter_id'];
                }else{
                    $s['up'] = '';
                }
                // 下翻，本身
                $s['down'] = $s['id'];

                $memberTree['son'][$k] = $s;
                $memberTree['son'][$k]['son'] = [];
                $sonson = $this->memberSon($s['id'],$fields);
                if($sonson):
                    foreach($sonson as $kk => $ss):
                        // 上翻
                        $ss_seters = $ss['seters'];
                        if(sizeof($ss_seters)>=3){
                            // 上级超过3层可以上翻
                            $ss['up'] = $memberTree['seter_id'];
                        }else{
                            $ss['up'] = '';
                        }
                        // 下翻
                        $ss['down'] = $s['id'];
                        $memberTree['son'][$k]['son'][$kk] = $ss;
                    endforeach;
                else:
                    $memberTree['son'][$k]['son'] = [];
                endif;
            
            endforeach;
        else:
            $memberTree['son'] = [];
        endif;

        return $memberTree;
    }

    public function memberSon($uid,$fields){
        $data = $this->where(['seter_id'=>$uid])->field('id')->select();
        if($data){
            foreach($data as &$value):
                $id=$value['id'];
                $value=$this->getOneDataById($id,$fields);
            endforeach;
        }else{
            $data = [];
        }
        return $data;
    }

    /**
     * 查询登录用户
     * @return [type] [description]
     */
    public function getLoginMember($loginname){
        $row = $this->where(['mid'=>$loginname])->whereOr(['phone'=>$loginname])->find();
        if(!$row){
            $this->error='会员不存在';
            return false;
        }
        if($row['status']==3){
            $this->error='会员帐号被禁用';
            return false;
        }
        if($row['status']==4){
            $this->error='会员帐号被冻结';
            return false;
        }
        $row = $row->toArray();
        $uid = $row['id'];
        $member = $this->getOneDataById($uid);
        return $member;
    }

    public function setField($row){

        if(isset($row['init_level'])){
            $row['init_level_name'] = Level::levelData($row['init_level'])['level_name'];
        }
        if(isset($row['level_id'])){
            $row['level_name'] = Level::levelData($row['level_id'])['level_name'];
        }
        if(isset($row['agent_type_id'])){
            $row['agent_type_name'] = $row['agent_type_id']?AgentType::agentTypeData($row['agent_type_id'])['type_name']:'';
        }
        if(isset($row['is_agent'])){
            $row['is_agent_remark'] = $row['is_agent']==1?'是':'否';
        }
        if(isset($row['area'])){
            $row['area_remark'] = $row['area']==1?'A区':'B区';
        }
        if(isset($row['type'])){
            $row['type_remark'] = $row['type']==1?'空单':'实单';
        }
        if(isset($row['status'])){
            $row['status_remark'] = self::$status_remark[$row['status']];
        }
        if(isset($row['is_phone_checked'])){
            $row['is_phone_checked_remark'] = $row['is_phone_checked']==1?'已验证':'未验证';
        }
        if(isset($row['city'])){
            // 地址处理
            $code = $row['city'];
            // 省
            $row['address_province'] = substr($row['city'], 0,strlen($row['city'])-4);
            // 市
            $row['address_city'] = substr($row['city'], 0,strlen($row['city'])-2);
            // 县
            $row['address_county'] = $row['city'];
        }
        return $row;
    }


    /**
     * 添加会员
     * @param [type] $data [description]
     */
    public function addMember($data){
        // $model = new MemberModel;
        
        // 补全会员数据
        $member = $this->initMemberData($data);

        // 空单
        if($data['type'] == 1) {
            // 添加会员
            $this->allowField(true)->save($member);
            $uid = $this->getLastInsID();
            // 处理安置人路径，返回所在层级
            $floor = $this->setSeters($uid,$member['seter_id'],$member['area']);
            // 处理推荐人路径
            $this->setInviters($uid,$member['inviter_id']);
            // 初始化会员账户
            $this->initAccount($uid,$member['level_id'],$member['type']);
            $this->save(['floor'=>$floor],['id'=>$uid]);
            // 会员数量统计
            model('level')->where(['id'=>$member['level_id']])->setInc('member_count');
            $CACHE = \app\common\cache\CacheData::getInstance('Level');
            $CACHE -> updateCache();
            return true;
        }
        $this->startTrans();
        try {
            // 添加会员
            $this->allowField(true)->save($member);
            $uid = $this->getLastInsID();

            // 处理安置人路径，返回所在层级
            $floor = $this->setSeters($uid,$member['seter_id'],$member['area']);
            // 处理推荐人路径
            $this->setInviters($uid,$member['inviter_id']);

            // 激活
            if(false===$this->active($uid,$member['agent_id'],$member['level_id'])){
                exception($this->error);
            }

            // 初始化会员账户
            $this->initAccount($uid,$member['level_id'],$member['type']);
            
            $score = Level::levelData($member['level_id'])['score'];
            // 更新状态
            $this->save(['status'=>1, 'score_own'=>$score,'floor'=>$floor],['id'=>$uid]);
            // 业绩记录
            $memberScoreModel = model('member_score');
            $scoreData = ['uid'=>$uid,'score'=>$score,'type'=>'register'];
            $memberScoreModel->save($scoreData);
            $scoreId = $memberScoreModel->id;
            
            // 发布消息队列
            $actionData = [
                    'uid'=>$uid,
                    'score'=>$score,
                    'level_id'=>$member['level_id'],
                    'agent_uid'=>$member['agent_id'],
                    'type' => 'register'
                ];
            $this->publishActions($actionData,$scoreId);

            // 会员数量统计
            model('level')->where(['id'=>$member['level_id']])->setInc('member_count');
            $CACHE = \app\common\cache\CacheData::getInstance('Level');
            $CACHE -> updateCache();
            
            $this->commit();
        } catch (\Exception $e) {
            $this->error = $e->getMessage();
            $this->rollback();
            return false;
        }
        return $scoreId;

    }
    /**
     * 初始化会员数据
     * @param  [type] $data [description]
     * @return [type]       [description]
     */
    private function initMemberData($data){
        // 用户状态，空单可用，实单待审核
        $data['status'] = $data['type']==1?1:2;
        // 初始等级
        $data['init_level'] = $data['level_id'];
        // 密码加密
        $data['password'] = hashPwd($data['password']);
        // 交易密码加密
        $data['safe_password'] = hashPwd($data['safe_password']);
        // 安置人id
        $data['seter_id'] = $this->where(['mid'=>strtoupper($data['seter_id'])])->value('id');
        // 邀请人id
        $data['inviter_id'] = $this->where(['mid'=>strtoupper($data['inviter_id'])])->value('id');
        // 安置人id
        $data['agent_id'] = $this->where(['mid'=>strtoupper($data['agent_id'])])->value('id');

        return $data;
    }
    /**
     * 设置安置人路径
     * @param [type] $uid       [description]
     * @param [type] $seter_uid [description]
     * @param [type] $area      [description]
     */
    private function setSeters($uid,$seter_uid,$area){
        // 查询安置人的安置路径
        $seter_seters = model('member_seter')->getSetersByUid($seter_uid);
        if(!$seter_seters){
            // 如果安置人的安置人路径为空，则安置人为顶级用户
            $my_seters = [
                [
                    'uid' => $uid,
                    'index' => 0,
                    'seter_uid' => $seter_uid,
                    'area' => $area
                ]
            ];
        }else{
            // 否则，在安置人路径基础上，加一条安置人本身
            $seter_seters_num = sizeof($seter_seters);
            $my_seters = [];
            foreach($seter_seters as $seter):
                $seter['uid'] = $uid;
                unset($seter['id']);
                unset($seter['seter_level']);
                $my_seters[]=$seter;
            endforeach;
            $my_seters[] = [
                'uid' => $uid,
                'index' => $seter_seters_num,
                'seter_uid' => $seter_uid,
                'area' => $area
            ];
        }
        model('member_seter')->saveAll($my_seters);
        return sizeof($my_seters)+1;
    }
    /**
     * 设置推荐人路径
     * @param [type] $uid         [description]
     * @param [type] $inviter_uid [description]
     */
    private function setInviters($uid,$inviter_uid){
        // 查询推荐人推荐路径
        $inviter_inviters = model('member_inviter')->getInvitersByUid($inviter_uid);
        if(!$inviter_inviters){
            // 如果推荐人的推荐人路径为空，则推荐人为顶级用户
            $my_inviters = [
                [
                    'uid' => $uid,
                    'index' => 0,
                    'inviter_uid' => $inviter_uid,
                    'floor' => 0,
                ]
            ];
        }else{
            // 否则，在推荐人路径基础上，加一条推荐人本身
            $inviter_inviters_num = sizeof($inviter_inviters);
            $my_inviters = [];
            foreach($inviter_inviters as $inviter):
                $inviter['uid'] = $uid;
                $inviter['floor'] += 1;
                unset($inviter['id']);
                $my_inviters[]=$inviter;
            endforeach;
            $my_inviters[] = [
                'uid' => $uid,
                'index' => $inviter_inviters_num,
                'inviter_uid' => $inviter_uid,
                'floor'=>0,
            ];
        }
        model('member_inviter')->saveAll($my_inviters);
    }
    /**
     * 初始化会员账户
     * @param  [type] $uid      [description]
     * @param  [type] $level_id [description]
     * @param  [type] $type     [description]
     * @return [type]           [description]
     */
    private function initAccount($uid,$level_id,$type){
        $coinData = Coin::coinData();
        // 所有货币类型金额初始化为0
        $defaultAccount = [];
        foreach($coinData as $coin):
            $defaultAccount[] = [
                'uid' => $uid,
                'coin_id' => $coin['id'],
                'amount' => 0,
            ];
        endforeach;
        model('member_coin')->saveAll($defaultAccount);

        // 初始化AB大区剩余业绩，都为0
        $defaultAreaScore = [
            ['uid'=>$uid,'area'=>1,'score'=>0],
            ['uid'=>$uid,'area'=>2,'score'=>0]
        ];
        model('member_area_score')->saveAll($defaultAreaScore);

        // 如果是实单
        if($type==2):
            // 读取注册获取配置
            $levelCoinConfig = LevelCoinConfig::levelCoinConfigByType('register');
            // 等级为用户等级的注册获取配置
            foreach($levelCoinConfig as $config):
                if($config['level_id']==$level_id){
                    $data[] = [
                        'uid'=>$uid,
                        'coin_id'=>$config['coin_id'],
                        'amount'=>$config['config']
                    ];
                }
            endforeach;
            model('member_coin')->saveAll($data);
        endif;
    }
    /**
     * 激活会员
     * @param  [type] $uid       [description]
     * @param  [type] $agent_uid [description]
     * @param  [type] $level_id  [description]
     * @return [type]            [description]
     */
    public function active($uid,$agent_uid,$level_id){
        // 查询代理中心的代理类型
        $agent_type_id = $this->where(['id'=>$agent_uid])->value('agent_type_id');
        // 获取该代理类型的激活配置
        $configData = AgentTypeLevelCoinConfig::agentTypeConfig($agent_type_id);
        $levelConfig = $configData[$level_id];
        $config = $levelConfig['config'];

        // 获取代理中心账户余额
        $agentAccount = model('member_coin')->getAccountByUid($agent_uid);
        $agentAccount= array_combine(array_column($agentAccount,'coin_id'),$agentAccount);

        // 获取等级业绩金额
        $levelAmount = Level::levelData($level_id)['amount'];
        
        foreach($config as $conf):
            // 判断代理中心扣币是否充足
            $decreaceAmount = $levelAmount*$conf['config']/100;
            
            if($decreaceAmount>$agentAccount[$conf['coin_id']]['amount']){
                $this->error='代理中心'.$agent_id.'的'.$conf['coin_name'].'不足';
                return false;
            }
            $where = ['uid'=>$agent_uid,'coin_id'=>$conf['coin_id']];
            $beforeAmount = model('member_coin')->where($where)->value('amount');
            // 扣除代理中心货币
            model('member_coin')->where($where)->setDec('amount',$decreaceAmount);
            $afterAmount = model('member_coin')->where($where)->value('amount');
            // 资金变动记录
            $record[] = [
                'operate_id' => 0,
                'uid' => $agent_uid,
                'coin_id' => $conf['coin_id'],
                'amount' => $decreaceAmount,
                'operate' => __FUNCTION__,
                'before_amount' => $beforeAmount,
                'after_amount' => $afterAmount,
                'remark' => '激活【'.$uid.'】扣币',
                'flag' => 'dec'
            ];
        endforeach;

        model('member_coin_record')->saveAll($record);
        return true;

    }

    /**
     * 原点升级
     * @param  [type] $uid         [description]
     * @param  [type] $agent_id    [description]
     * @param  [type] $level_id    [description]
     * @param  [type] $up_level_id [description]
     * @return [type]              [description]
     */
    public function upgrade($uid,$agent_id,$level_id,$up_level_id){
        // 当前等级业绩
        $level = Level::levelData($level_id);
        $level_score = $level['score'];
        // 目标等级业绩
        $up_level = Level::levelData($up_level_id);
        $up_level_score = $up_level['score'];
        // 该会员所在代理中心类型
        $memberModel = model('member');
        $agent_type_id = $memberModel->where(['id'=>$agent_id])->value('agent_type_id');
        // 该代理中心在当前等级的激活配置
        $activeConfig = AgentTypeLevelCoinConfig::agentTypeConfig($agent_type_id);
        $levelConfig = $activeConfig[$level_id];
        $levelConfig = $levelConfig['config'];
        $levelConfig = array_combine(array_column($levelConfig, 'coin_id'),$levelConfig);
        $levelCoins = array_keys($levelConfig);
        // 该代理中心在目标等级的激活配置
        $upLevelConfig = $activeConfig[$up_level_id];
        $upLevelConfig = $upLevelConfig['config'];
        $upLevelConfig = array_combine(array_column($upLevelConfig, 'coin_id'),$upLevelConfig);
        $uplevelCoins = array_keys($upLevelConfig);
        // 判断货币配置结构是否一致
        sort($levelCoins);
        sort($uplevelCoins);
        if($levelCoins != $uplevelCoins){
            $this->error = '当前等级与目标等级的货币激活配置结构不一致，升级失败';
            return false;
        }
        // 待扣币计算
        $waitDecAmount = [];
        foreach($upLevelConfig as $config):
            $waitDecAmount[$config['coin_id']] = $up_level_score*$config['config']/100-$level_score*$levelConfig[$config['coin_id']]['config']/100;
        endforeach;

        // 执行扣币与升级
        $memberCoinModel = model('member_coin');
        $account = $memberCoinModel->getAccountByUid($uid);
        $account = array_combine(array_column($account, 'coin_id'),$account);

        $memberCoinModel -> startTrans();
        try{
            // 升级记录
            $upgradeModel = model('operate_upgrade');
            $upgradeData = [
                'uid' => $uid,
                'level_id' => $level_id,
                'up_level_id' => $up_level_id
            ];
            $upgradeModel -> save($upgradeData);
            $operate_id = $upgradeModel->getLastInsID();

            // 资金变动记录
            $records = [];
            // 该会员余额判断与扣币
            foreach($waitDecAmount as $key => $value):
                if($account[$key]['amount']<$value){
                    exception($account[$key]['coin_name'].'不足，升级失败');
                }
                $beforeAmount = $memberCoinModel -> where(['uid'=>$uid,'coin_id'=>$key])->value('amount');
                $memberCoinModel -> where(['uid'=>$uid,'coin_id'=>$key]) -> setDec('amount',$value);
                $afterAmount = $memberCoinModel -> where(['uid'=>$uid,'coin_id'=>$key])->value('amount');

                // 资金变动记录
                $records[] = [
                    'operate_id' => $operate_id,
                    'uid' => $uid,
                    'coin_id' => $key,
                    'amount' => $value,
                    'operate' => __FUNCTION__,
                    'before_amount' => $beforeAmount,
                    'after_amount' => $afterAmount,
                    'remark' => '['.$uid.']从['.$level['level_name'].']升级到['.$up_level['level_name'].']扣币',
                    'flag' => 'dec'
                ];
            endforeach;
            // 保存资金变动记录
            model('member_coin_record')->saveAll($records);
            // 新增系统业绩
            $score = $up_level_score-$level_score;
            $score_own = $up_level_score;
            // 更新会员表个人业绩，开启全体分红与加权分红
            $memberModel->where(['id'=>$uid])->update(['score_own'=>$up_level_score,'is_world'=>1,'is_share'=>1]);
            // 业绩记录
            $memberScoreModel = model('member_score');
            $scoreData = ['uid'=>$uid,'score'=>$score,'type'=>'upgrade'];
            $memberScoreModel -> save($scoreData);
            $scoreId = $memberScoreModel->getLastInsID();
            
            // 发布消息队列
            $actionData = [
                    'uid'=>$uid,
                    'score'=>$score,
                    'level_id'=>$up_level_id,
                    'agent_uid'=>$agent_id,
                    'type'=>'upgrade'
                ];
            $this->publishActions($actionData,$scoreId);

            // 变更用户等级
            $memberModel -> where('id',$uid) -> update(['level_id'=>$up_level_id]);
            // 变更升级记录状态
            $upgradeModel -> where('id',$operate_id) -> update(['status'=>1]);

            // 会员数量统计
            $levelModel = new \app\common\model\Level;
            $levelModel -> where(['id'=>$level_id])->setDec('member_count');
            $levelModel -> where(['id'=>$up_level_id])->setInc('member_count');
            $memberCoinModel->commit();
        }catch(\Exception $e){
            $memberCoinModel->rollback();
            $this->error = $e->getMessage();
            return false;
        }
        return true;
    }
    
    /**
     * 发布奖金消息队列
     * @param  [type] $actionData [description]
     * @param  [type] $scoreId    [description]
     * @return [type]             [description]
     */
    private function publishActions($actionData,$scoreId){
        // 发布消息队列
        $actions = [
            [
                'operate_id' => $scoreId,
                'action_name' => 'lingshou',
                'action_data' => serialize($actionData),
            ],
            [
                'operate_id' => $scoreId,
                'action_name' => 'xiaoshou',
                'action_data' => serialize($actionData),
            ],
            [
                'operate_id' => $scoreId,
                'action_name' => 'fuwu',
                'action_data' => serialize($actionData),
            ],
            [
                'operate_id' => $scoreId,
                'action_name' => 'score',
                'action_data' => serialize($actionData),
            ]
        ];
        model('bonus_action')->saveAll($actions);
    }

}
